home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 001-025 / disk_005 / speechtoysrc / speechtoy.c
C/C++ Source or Header  |  1992-05-06  |  49KB  |  1,391 lines

  1. /* !!! To those who haven't figured it out yet:
  2.  * !!! set stack to 15000 before compiling.
  3.  * !!! This is a generally good thing to do if
  4.  * !!! the compiler blows up on a large source.
  5.  * !!! if your program suddenly KILLS the compiler,
  6.  * !!! increase stack by 5K and try again. jeeze you guys.
  7.  */
  8. /* This program was written to show the use of gadgets in a
  9.  * window. Thus one menu, one auto requester, but lots of
  10.  * gadget types.
  11.  * For the sake of example, two mutual exclude gadgets
  12.  * (female/male) are shown that perform a function that might
  13.  * be better implemented as a toggle image, in a manner similar
  14.  * to that shown in the inflection Mode gadget.
  15.  * Again for the sake of example, the proportional gadgets
  16.  * are generated dynamicly (that is, copied from a template and
  17.  * filled in), whereas most gadgets are declared staticly in
  18.  * the struct declaration, which saves the initialization code
  19.  * space.
  20.  * Lastly, for the sake of example, this program is extremely
  21.  * verbose in the way of comments. Hope you don't mind.
  22.  */
  23. /* Written by David M Lucas. */
  24. /* This program Copyright (C) 1985 David Lucas */
  25. /* This program is not to be sold for commercial gain. */
  26. /* Use it as an example, and PIECES MAY BE PLAGIARISED FREELY */
  27. /* If you find somthing you don't like, fix it! Have fun! */
  28. /* Send complaints to /dev/null. really. */
  29. /* Thanks Amiga. */
  30.  
  31. #include "exec/types.h"
  32. #include "exec/exec.h"
  33. #include "intuition/intuition.h"
  34. #include "intuition/intuitionbase.h"
  35. #include "graphics/regions.h"
  36. #include "graphics/copper.h"
  37. #include "graphics/gels.h"
  38. #include "graphics/gfxbase.h"
  39. #include "devices/keymap.h"
  40. #include "hardware/blit.h"
  41. #include "devices/narrator.h"
  42. #include "libraries/translator.h"
  43.  
  44. /* #define DEBUG */
  45.  
  46. #define CONTWINDW 321 /* Overall Control Window Width/Height */
  47. #define CONTWINDH 123
  48. #define FACEWINDW 32  /* Overall Face Window Width / Height */
  49. #define FACEWINDH 44  /* this includes borders, incedently */
  50.  
  51. /* Pen numbers to draw gadget borders/images/text with */
  52. #define REDP   3        /* color in register 3 once was red */
  53. #define BLKP   2        /* color in register 2 was black */
  54. #define WHTP   1        /* color in register 1 was white */
  55. #define BLUP   0        /* color in register 0 was blue */
  56.  
  57. /* the length of the English and phonetic buffers */
  58. #define ESTRINGSIZE 512
  59. #define PSTRINGSIZE 768 /* phonemes are longer than english */
  60.  
  61. #define NUMPROPS 4      /* number of proportional gadgets */
  62.  
  63. /* Ranges of proportional data */
  64. #define RNGFREQ  (MAXFREQ  - MINFREQ)  +1
  65. #define RNGRATE  (MAXRATE  - MINRATE)  +1
  66. #define RNGPITCH (MAXPITCH - MINPITCH) +1
  67. #define RNGVOL   (MAXVOL   - MINVOL)   +1
  68.  
  69. struct TextAttr TestFont = /* Needed for opening screen */
  70.    {
  71.    (STRPTR)"topaz.font",
  72.    TOPAZ_EIGHTY, 0, 0
  73.    };
  74.  
  75. /* Which audio channels to use */
  76. BYTE audio_chan[] = {3, 5, 10, 12};
  77. /* Pointer to translator library vectors */
  78. struct Library *TranslatorBase = 0;
  79. struct MsgPort talk_port; /* Message port for the say's I/O  */
  80. struct MsgPort read_port; /* Message port for the say's I/O  */
  81. struct mouth_rb mouth_io;  /* IO Request block, mouth flavor */
  82. /* IO Request block, narrator flavor */
  83. struct narrator_rb voice_io;
  84. /* indicative of the Open return */
  85. UBYTE NarratorOpenError = 0;
  86. /* indicative of a Translations success */
  87. UBYTE TranslatorError = 0;
  88. USHORT i;
  89.  
  90. /* These are used to draw the eyes and mouth size relative */
  91. USHORT MouthWMult;
  92. USHORT EyesLeft;
  93. USHORT MouthHMult;
  94. USHORT EyesTop;
  95. USHORT EyesBottom;
  96. USHORT YMouthCenter;  /* Pixels from top edge */
  97. USHORT XMouthCenter;  /* Pixels from left edge */
  98. USHORT yaw;
  99. USHORT LipWidth, LipHeight;
  100.  
  101. /* String Gadgets *********************************************
  102.  * First the string gadgets.
  103.  * 1) because the Phonetic string is refreshed programaticly
  104.  * (that is, deleted and added again) quite often, and doing
  105.  * this requires the use of RefreshGadgets(), and this causes
  106.  * gadgets that are closer to the beginning of the list than
  107.  * the gadget given to RefreshGadgets() to flicker.
  108.  * 2) because they don't flicker when OTHER gadgets
  109.  * (ie female/male, coming up) are deleted and added.
  110.  */
  111. /* These'll be used to put a nice double line border around
  112.  * each of the two string gadgets.
  113.  */
  114. /* y,x pairs drawn as a connected line. Be sure to have an even
  115.  * number of arguments (ie complete pairs).
  116.  */
  117.  
  118. USHORT StrVectors[] = {
  119.    0, 0,   297, 0,   297, 14,   0, 14,
  120.    0, 1,   296, 1,   296, 13,   1, 13,
  121.    1, 1
  122. };
  123. struct Border StrBorder = {
  124.    -4, -3,           /* initial offsets, gadget relative */
  125.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  126.    9,                /* number of vectors */
  127.    StrVectors,     /* pointer to the actual array of vectors */
  128.    NULL       /* no next Border, can point to another border */
  129. };
  130.  
  131. /* The same undo buffer is used for both string gadgets,
  132.  * this is sized to largest so that largest fits.
  133.  */
  134. UBYTE UndoBuffer[PSTRINGSIZE];
  135.  
  136. /* English String Gadget is where the user types in English */
  137. /* default text */
  138. UBYTE EnglBuffer[ESTRINGSIZE] = "This is amiga speaking.";
  139. struct StringInfo EnglInfo = {
  140.    EnglBuffer,    /* pointer to I/O buffer */
  141.    UndoBuffer,    /* pointer to undo buffer */
  142.    0,             /* buffer position */
  143.    ESTRINGSIZE,   /* max number of chars, including NULL */
  144.    0, 0,          /* first char in display, undo positions */
  145.    24,          /* number of chars (currently) in the buffer */
  146.    0, 0, 0,    /* position variables calculated by Intuition */
  147.    NULL,          /* no pointer to RastPort */
  148.    0,             /* not a LongInt string gadget */
  149.    NULL           /* no pointer to alternate keymap */
  150. };
  151. struct IntuiText EnglText = {
  152.    WHTP, BLUP,    /* FrontPen, BackPen */
  153.    JAM1,          /* DrawMode */
  154.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  155.    &TestFont,     /* pointer to TextFont */
  156.    "English:",    /* pointer to Text */
  157.    NULL           /* no pointer to NextText */
  158. };
  159. struct Gadget EnglStrGadget = {
  160.    NULL,             /* pointer to Next Gadget */
  161.    11, 63, 290, 10,  /* (Left Top Width Height) Hit Box */
  162.    GADGHCOMP,        /* Flags */
  163.    RELVERIFY,        /* Activation flags */
  164.    STRGADGET,        /* Type */
  165.    (APTR)&StrBorder, /* pointer to Border Image */
  166.    NULL,             /* no pointer to SelectRender */
  167.    &EnglText,        /* pointer to GadgetText */
  168.    0,                /* no MutualExclude */
  169.    (APTR)&EnglInfo,  /* pointer to SpecialInfo */
  170.    0,                /* no ID */
  171.    NULL              /* no pointer to special data */
  172. };
  173.  
  174. /* Phonetic string gadget is where the program puts the
  175.  * translated string, necessating a call to RefreshGadgets(),
  176.  * and is where the user can type in Phonemes.
  177.  */
  178. UBYTE PhonBuffer[PSTRINGSIZE] =
  179.   "DHIHS IHZ AHMIY3GAH SPIY4KIHNX.";
  180. struct StringInfo PhonInfo = {
  181.    PhonBuffer,    /* pointer to input buffer */
  182.    UndoBuffer,    /* pointer to undo buffer */
  183.    0,             /* initial buffer position */
  184.    PSTRINGSIZE,   /* max number of chars, including NULL */
  185.    0, 0,          /* display, undo positions */
  186.    32,          /* number of chars (currently) in the buffer */
  187.    0, 0, 0,    /* position variables calculated by Intuition */
  188.    NULL,          /* no pointer to RastPort */
  189.    NULL,          /* not a LongInt string gadget */
  190.    NULL           /* no pointer to alternate keymap */
  191. };
  192. struct IntuiText PhonText = {
  193.    WHTP, BLUP,    /* FrontPen, BackPen */
  194.    JAM1,          /* DrawMode */
  195.    0, -13,        /* LeftEdge, TopEdge (relative to gadget) */
  196.    &TestFont,     /* pointer to TextFont */
  197.    "Phonetics:",  /* pointer to Text */
  198.    NULL           /* no pointer to NextText */
  199. };
  200. struct Gadget PhonStrGadget = {
  201.    &EnglStrGadget,   /* pointer to Next Gadget */
  202.    11, 94, 290, 10,  /* (Left Top Width Height) Hit Box */
  203.    GADGHCOMP,        /* Flags */
  204.    RELVERIFY,        /* Activation flags */
  205.    STRGADGET,        /* Type */
  206.    (APTR)&StrBorder, /* pointer to Border Image */
  207.    NULL,             /* no pointer to SelectRender */
  208.    &PhonText,        /* pointer to GadgetText */
  209.    0,                /* no MutualExclude */
  210.    (APTR)&PhonInfo,  /* pointer to SpecialInfo */
  211.    0,                /* no ID */
  212.    NULL              /* no pointer to special data */
  213. };
  214.  
  215. /* Now come the Boolean Gadgets.
  216.  * The female/male pair shows the simplest implementation I
  217.  * could think of to show how you can do mutual-exclude type
  218.  * things yourself. They are two toggle gadgets that use
  219.  * highlight image. The program starts with one selected, and
  220.  * then if either of them are hit, both toggle. Gadgets must
  221.  * be deleted and added whenever you want to change structure
  222.  * member values that intuition expects to be coming from the
  223.  * user, not a program (like the SELECTED bit in flags). Note
  224.  * that certain structure values CAN be changed programaticly
  225.  * without all this broohaha. Haha. Consult the intuition
  226.  * manual.
  227.  */
  228. /* Female Toggle (Highlight Image)
  229.    (Quasi mutual exclude with Male Toggle) */
  230. struct Image FemaleImage = {
  231.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  232.    20, 10, 1,  /* Width, Height, Depth */
  233.    NULL,       /* pointer to ImageData */
  234.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  235. };
  236. struct Gadget FemaleGadget = {
  237.    &PhonStrGadget,      /* pointer to Next Gadget */
  238.    134, 34, 20, 10,     /* (Left Top Width Height) Hit Box */
  239.    GADGIMAGE | GADGHCOMP,  /* Flags */
  240.    /* Activation flags */
  241.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  242.    BOOLGADGET,          /* Type */
  243.    (APTR)&FemaleImage,  /* pointer to GadgetRender */
  244.    NULL,                /* no pointer to SelectRender */
  245.    NULL,                /* no pointer to GadgetText */
  246.    0,                   /* no MutualExclude */
  247.    NULL,                /* no pointer to SpecialInfo */
  248.    0,                   /* no ID */
  249.    NULL                 /* no pointer to special data */
  250. };
  251.  
  252. /* Male Toggle (Highlight Image)
  253.    (Quasi mutual Exclude with above) */
  254. struct Image MaleImage = {
  255.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  256.    20, 10, 1,  /* Width, Height, Depth */
  257.    NULL,       /* pointer to ImageData */
  258.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  259. };
  260. struct Gadget MaleGadget = {
  261.    &FemaleGadget,    /* pointer to Next Gadget */
  262.    154, 34, 20, 10,  /* (Left Top Width Height) Hit Box */
  263.    GADGIMAGE | GADGHCOMP | SELECTED,   /* Flags */
  264.    /* Activation flags */
  265.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT | ACTIVATE,
  266.    BOOLGADGET,       /* Type */
  267.    (APTR)&MaleImage, /* pointer to GadgetRender */
  268.    NULL,             /* no pointer to SelectRender */
  269.    NULL,             /* no pointer to GadgetText */
  270.    0,                /* no MutualExclude */
  271.    NULL,             /* no pointer to SpecialInfo */
  272.    0,                /* no ID */
  273.    NULL              /* no pointer to special data */
  274. };
  275.  
  276. /* This boolean toggle gadget has an
  277.  * alternate image that indicates
  278.  * selection. The image stays flipped
  279.  * until it gets another hit. (it toggles)
  280.  */
  281. /* Inflection Mode Toggle (AltImage) *************************/
  282. struct Image HumanImage = {
  283.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  284.    40, 20, 1,  /* Width, Height, Depth */
  285.    NULL,       /* pointer to ImageData */
  286.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  287. };
  288. struct Image RobotImage = {
  289.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  290.    40, 20, 1,  /* Width, Height, Depth */
  291.    NULL,       /* pointer to ImageData */
  292.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  293. };
  294. struct Gadget ModeGadget = {
  295.    &MaleGadget,            /* pointer to Next Gadget */
  296.    134, 2, 40, 20,        /* (Left Top Width Height) Hit Box */
  297.    GADGIMAGE | GADGHIMAGE, /* Flags */
  298.    /* Activation flags */
  299.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  300.    BOOLGADGET,             /* Type */
  301.    (APTR)&HumanImage,      /* pointer to GadgetRender */
  302.    (APTR)&RobotImage,      /* pointer to SelectRender */
  303.    NULL,                   /* no pointer to GadgetText */
  304.    0,                      /* no MutualExclude */
  305.    NULL,                   /* no pointer to SpecialInfo */
  306.    0,                      /* no ID */
  307.    NULL                    /* no pointer to special data */
  308. };
  309.  
  310. /* Face Toggle (image and text) ******************************/
  311. struct IntuiText FaceIText = {
  312.    WHTP, BLUP, /* FrontPen, BackPen */
  313.    JAM2,       /* DrawMode */
  314.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  315.    &TestFont,  /* pointer to TextFont */
  316.    "Face",/* pointer to Text */
  317.    NULL        /* no pointer to NextText */
  318. };
  319. struct Image FaceImage = {
  320.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  321.    40, 10, 1,  /* Width, Height, Depth */
  322.    NULL,       /* pointer to ImageData */
  323.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  324. };
  325. struct Gadget FaceGadget = {
  326.    &ModeGadget,            /* pointer to Next Gadget */
  327.    134, 23, 40, 10,       /* (Left Top Width Height) Hit Box */
  328.    GADGIMAGE | GADGHCOMP,  /* Flags */
  329.    /* Activation flags */
  330.    RELVERIFY | GADGIMMEDIATE | TOGGLESELECT,
  331.    BOOLGADGET,             /* Type */
  332.    (APTR) &FaceImage,      /* pointer to GadgetRender */
  333.    NULL,                   /* no pointer to SelectRender */
  334.    &FaceIText,             /* pointer to GadgetText */
  335.    0,                      /* no MutualExclude */
  336.    NULL,                   /* no pointer to SpecialInfo */
  337.    0,                      /* no ID */
  338.    NULL                    /* no pointer to special data */
  339. };
  340.  
  341. /* Stop Hit (image and text) ******************************/
  342. struct IntuiText StopIText = {
  343.    WHTP, BLUP, /* FrontPen, BackPen */
  344.    JAM2,       /* DrawMode */
  345.    4, 1,       /* LeftEdge, TopEdge (relative to gadget) */
  346.    &TestFont,  /* pointer to TextFont */
  347.    "Stop",/* pointer to Text */
  348.    NULL        /* no pointer to NextText */
  349. };
  350. struct Image StopImage = {
  351.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  352.    40, 10, 1,  /* Width, Height, Depth */
  353.    NULL,       /* pointer to ImageData */
  354.    0x1, 0x0    /* PlanePick, PlaneOnOff */
  355. };
  356. struct Gadget StopGadget = {
  357.    &FaceGadget,            /* pointer to Next Gadget */
  358.    134, 45, 40, 10,        /* Left Top Width Height Hit Box */
  359.    GADGIMAGE | GADGHCOMP,  /* Flags */
  360.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  361.    BOOLGADGET,             /* Type */
  362.    (APTR) &StopImage,      /* pointer to GadgetRender */
  363.    NULL,                   /* no pointer to SelectRender */
  364.    &StopIText,             /* pointer to GadgetText */
  365.    0,                      /* no MutualExclude */
  366.    NULL,                   /* no pointer to SpecialInfo */
  367.    0,                      /* no ID */
  368.    NULL                    /* no pointer to special data */
  369. };
  370.  
  371. /* This is a hit (as opposed to toggle)
  372.    gadget that starts the translation.*/
  373. /* Translate Hit (Highlight image) ***************************/
  374. USHORT TransVectors[] = {
  375.    0, 0,    79, 0,    79, 13,   0, 13,
  376.    0, 1,    78, 1,    78, 12,   1, 12,
  377.    1, 1
  378. };
  379. struct Border TransBorder = {
  380.    -4, -3,           /* initial offsets, gadget relative */
  381.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  382.    9,                /* number of vectors */
  383.    TransVectors,     /* pointer to the array of vectors */
  384.    NULL              /* no next Border, can point to another */
  385. };
  386. struct IntuiText TranslateIText = {
  387.    WHTP, BLUP, /* FrontPen, BackPen */
  388.    JAM2,       /* DrawMode */
  389.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  390.    &TestFont,  /* pointer to TextFont */
  391.    "Translate",/* pointer to Text */
  392.    NULL        /* no pointer to NextText */
  393. };
  394. struct Gadget TranslateGadget = {
  395.    &StopGadget,      /* pointer to Next Gadget */
  396.    229, 48, 71, 8,   /* (Left Top Width Height) Hit Box */
  397.    GADGHCOMP,        /* Flags */
  398.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  399.    BOOLGADGET,       /* Type */
  400.    (APTR)&TransBorder,  /* no pointer to GadgetRender */
  401.    NULL,             /* no pointer to SelectRender */
  402.    &TranslateIText,  /* pointer to GadgetText */
  403.    0,                /* no MutualExclude */
  404.    NULL,             /* no pointer to SpecialInfo */
  405.    0,                /* no ID */
  406.    NULL              /* no pointer to special data */
  407. };
  408.  
  409. /* This is a hit (as opposed to toggle) Starts the narration */
  410. /* Speak Hit (Highlight Image) *******************************/
  411. USHORT SpeakVectors[] = {
  412.    0, 0,    47, 0,    47, 13,   0, 13,
  413.    0, 1,    46, 1,    46, 12,   1, 12,
  414.    1, 1
  415. };
  416. struct Border SpeakBorder = {
  417.    -4, -3,           /* initial offsets, gadget relative */
  418.    WHTP, BLUP, JAM1, /* pens (fore, back) and drawmode */
  419.    9,                /* number of vectors */
  420.    SpeakVectors,   /* pointer to the actual array of vectors */
  421.    NULL       /* no next Border, can point to another border */
  422. };
  423. struct IntuiText SpeakIText = {
  424.    WHTP, BLUP, /* FrontPen, BackPen */
  425.    JAM2,       /* DrawMode */
  426.    0, 0,       /* LeftEdge, TopEdge (relative to gadget) */
  427.    &TestFont,  /* pointer to TextFont */
  428.    "Speak",    /* pointer to Text */
  429.    NULL        /* no pointer to NextText */
  430. };
  431. struct Gadget SpeakGadget = {
  432.    &TranslateGadget, /* pointer to Next Gadget */
  433.    261, 79, 40, 8,   /* (Left Top Width Height) Hit Box */
  434.    GADGHCOMP,        /* Flags */
  435.    RELVERIFY | GADGIMMEDIATE, /* Activation flags */
  436.    BOOLGADGET,       /* Type */
  437.    (APTR)&SpeakBorder,  /* pointer to GadgetRender */
  438.    NULL,             /* no pointer to SelectRender */
  439.    &SpeakIText,      /* pointer to GadgetText */
  440.    0,                /* no MutualExclude */
  441.    NULL,             /* no pointer to SpecialInfo */
  442.    0,                /* no ID */
  443.    NULL              /* no pointer to special data */
  444. };
  445.  
  446. /* Now the proportional gadgets. */
  447. /* Proportional Gadgets **************************************/
  448. /* The following variables are used to create proportional
  449.  * Gadgets. These variables will be filled in with copies of
  450.  * the generic Gadgetry below.
  451.  */
  452. SHORT PropCount = 0;       /* index to next available Gadget */
  453. struct IntuiText PTexts[NUMPROPS];/* get copies of TPropText */
  454. /* dummy AUTOKNOB Images are required */
  455. struct Image PImages[NUMPROPS];
  456. /* These get copies of TPropInfo */
  457. struct PropInfo PInfos[NUMPROPS];
  458. /* These get copies of TPropGadget */
  459. struct Gadget Props[NUMPROPS];
  460. struct IntuiText TPropText = {
  461.    WHTP, BLUP,   /* FrontPen, BackPen */
  462.    JAM1,         /* DrawMode */
  463.    0, -10,       /* LeftEdge, TopEdge (relative to gadget) */
  464.    &TestFont,    /* pointer to TextFont */
  465.    NULL,         /* pointer to Text is filled at runtime */
  466.    NULL          /* no pointer to NextText */
  467. };   
  468. struct PropInfo TPropInfo = {
  469.    AUTOKNOB | FREEHORIZ,  /* Flags */
  470.    0, 0,            /* Pots:  Horiz, Vert: both start at 0 */
  471.    0x1FFF, 0x1FFF,  /* Bodies: Horiz is 1/8, Vert is 1/8 */
  472.    0, 0, 0, 0, 0, 0 /* System usage stuff */
  473. };
  474. /* this is the template for the Gadget of a horizontal */
  475. /* Proportional Gadget */
  476. struct Gadget TPropGadget = {
  477.    &SpeakGadget,              /* pointer to NextGadget */
  478.    7, 12, 115, 10,            /* Select Box L T W H */
  479.    GADGHCOMP | GADGIMAGE,     /* Flags */
  480.    GADGIMMEDIATE | RELVERIFY, /* Activation flags */
  481.    PROPGADGET,                /* Type */
  482.    NULL,       /* pointer to Image filled in later */
  483.    NULL,       /* no pointer to SelectRender */
  484.    NULL,       /* no pointer to GadgetText */
  485.    0,          /* no MutualExclude */
  486.    NULL,       /* SpecialInfo proportional data filled later */
  487.    0,          /* no ID */
  488.    NULL        /* no pointer to special data */
  489. };
  490.  
  491. struct IntuitionBase *IntuitionBase = 0;
  492. struct GfxBase *GfxBase = 0;
  493.  
  494. /* Only one menu. */
  495.  
  496. ULONG MenuNumber;
  497. ULONG TheMenu;
  498. ULONG TheItem;
  499.  
  500. struct IntuiText MenuItemText = {
  501.    BLUP,         /* Front Pen */
  502.    WHTP,         /* Back pen */
  503.    JAM2,         /* Draw Mode */
  504.    0,            /* Left Edge */
  505.    0,            /* Top */
  506.    &TestFont,    /* pointer to TextFont */
  507.    "About SpeechToy...", /* text */
  508.    NULL          /* next */
  509. };
  510. struct MenuItem MyMenuItem = {
  511.    NULL,                /* pointer to next item */
  512.    0,                   /* left */
  513.    0,                   /* top */
  514.    150,                 /* width */
  515.    8,                   /* height */
  516.    ITEMTEXT | ITEMENABLED | HIGHCOMP,  /* flags */
  517.    0,                   /* no mutual exclude */
  518.    (APTR)&MenuItemText, /* Render */
  519.    NULL,                /* pointer to alternate image */
  520.    NULL,                /* Command "amiga" char */
  521.    NULL,                /* Sub Item */
  522.    MENUNULL             /* nextselect */
  523. };
  524.  
  525. struct Menu MyMenu = {
  526.    NULL,          /* pointer to next menu */
  527.    0,0,150,0,     /* left,0,Width,0 */
  528.    MENUENABLED,   /* flags */
  529.    "SpeachToy Menu",   /* menu name */
  530.    &MyMenuItem    /* First Item in list */
  531. };
  532.  
  533. struct IntuiText ReqText1 = {
  534.    BLUP,         /* Front Pen */
  535.    WHTP,         /* Back pen */
  536.    JAM2,         /* Draw Mode */
  537.    5,            /* Left Edge */
  538.    23,           /* Top */
  539.    &TestFont,    /* pointer to TextFont */
  540.    "Version 1.1  21 Dec, 1985",  /* text */
  541.    NULL          /* next */
  542. };
  543. struct IntuiText ReqText2 = {
  544.    BLUP,         /* Front Pen */
  545.    WHTP,         /* Back pen */
  546.    JAM2,         /* Draw Mode */
  547.    5,            /* Left Edge */
  548.    13,           /* Top */
  549.    &TestFont,    /* pointer to TextFont */
  550.    "Freeware - Public Domain ", /* text */
  551.    &ReqText1     /* next */
  552. };
  553. struct IntuiText ReqText3 = {
  554.    BLUP,         /* Front Pen */
  555.    WHTP,         /* Back pen */
  556.    JAM2,         /* Draw Mode */
  557.    5,            /* Left Edge */
  558.    3,            /* Top */
  559.    &TestFont,    /* pointer to TextFont */
  560.    "Written by David M Lucas ", /* text */
  561.    &ReqText2     /* next */
  562. };
  563.  
  564. struct IntuiText OKIText = {
  565.    BLUP, WHTP, /* FrontPen, BackPen */
  566.    JAM2,       /* DrawMode */
  567.    6, 3,       /* LeftEdge, TopEdge (relative to gadget) */
  568.    &TestFont,  /* pointer to TextFont */
  569.    "OK",       /* pointer to Text */
  570.    NULL        /* no pointer to NextText */
  571. };
  572.  
  573. struct Requester *AboutRequester;
  574.  
  575. USHORT autoret;
  576. struct Window *ControlWindow = NULL;
  577. struct Window *FaceWindow = NULL;
  578. struct IntuiMessage *MyIntuiMessage;
  579. struct NewWindow NewControlWindow = {
  580.    00, 11,                    /* start LeftEdge, TopEdge */
  581.    CONTWINDW, CONTWINDH,      /* start Width, Height */
  582.    -1, -1,                    /* DetailPen, BlockPen */
  583.    GADGETUP | CLOSEWINDOW | MENUPICK,  /* IDCMP FLAGS */
  584.    WINDOWDRAG | WINDOWDEPTH | WINDOWCLOSE
  585.    | GIMMEZEROZERO | ACTIVATE,/* Flags (can be NULL) */
  586.    &Props[NUMPROPS-1],        /* Pointer to FirstGadget */
  587.    NULL,                    /* no pointer to first CheckMark */
  588.    "SpeechToy",               /* Title (can be NULL) */
  589.    NULL,                      /* no Pointer to Screen */
  590.    NULL,                      /* no Pointer to BitMap */
  591.    20, 20,                    /* Min/max  Sizable to (w/h) */
  592.    CONTWINDW, CONTWINDH,      /* These aint used, can't size */
  593.    WBENCHSCREEN         /* Type of screen window appears in */
  594. };
  595.  
  596. struct NewWindow NewFaceWindow = {
  597.    CONTWINDW, 11,             /* start LeftEdge, TopEdge */
  598.    FACEWINDW * 2, FACEWINDH,  /* start Width, Height */
  599.    -1, -1,                    /* DetailPen, BlockPen */
  600.    SIZEVERIFY | NEWSIZE | MENUPICK,      /* IDCMP FLAGS */
  601.    /* Flags (can be NULL) */
  602.    WINDOWDRAG | WINDOWDEPTH | WINDOWSIZING
  603.     | SIZEBBOTTOM | GIMMEZEROZERO | ACTIVATE,
  604.    NULL,                /* no Pointer to FirstGadget */
  605.    NULL,                /* no Pointer to first CheckMark */
  606.    "Face",              /* Title */
  607.    NULL,                /* no Pointer to Screen */
  608.    NULL,                /* no Pointer to BitMap */
  609.    FACEWINDW, FACEWINDH,/* Minimum sizeable to */
  610.    640, 200,            /* Maximum sizeable to */
  611.    WBENCHSCREEN         /* Type of screen window appears in */
  612. };
  613.  
  614. USHORT FemaleIData[] = {
  615. /*   ----    -  These nibbles matter to image. */
  616.    0x0000, 0x0000,
  617.    0x00F0, 0x0000,
  618.    0x0198, 0x0000,
  619.    0x030C, 0x0000,
  620.    0x0198, 0x0000,
  621.    0x00F0, 0x0000,
  622.    0x0060, 0x0000,
  623.    0x01F8, 0x0000,
  624.    0x0060, 0x0000,
  625.    0x0000, 0x0000
  626. };
  627.  
  628. USHORT MaleIData[] = {
  629. /*   ----    -   These nibbles matter to image. */
  630.    0x0000, 0x0000,
  631.    0x003E, 0x0000,
  632.    0x000E, 0x0000,
  633.    0x0036, 0x0000,
  634.    0x01E0, 0x0000,
  635.    0x0330, 0x0000,
  636.    0x0618, 0x0000,
  637.    0x0330, 0x0000,
  638.    0x01E0, 0x0000,
  639.    0x0000, 0x0000
  640. };
  641. USHORT HumanIData[] = {
  642. /*   ----   ----   --   These nibbles matter to image. */
  643.    0x0000,0x0000,0x0000,
  644.    0x0000,0x0000,0x0000,
  645.    0x0000,0x0000,0x0000,
  646.    0x0000,0x0000,0x0000,
  647.    0x0007,0x9E00,0x0000,
  648.    0x0001,0x8600,0x0000,
  649.    0x0000,0x0000,0x0000,
  650.    0x0000,0x0000,0x0000,
  651.    0x0000,0x2000,0x0000,
  652.    0x0000,0x1000,0x0000,
  653.    0x0000,0x0800,0x0000,
  654.    0x0000,0x7C00,0x0000,
  655.    0x0000,0x0000,0x0000,
  656.    0x0000,0x0000,0x0000,
  657.    0x0000,0x0000,0x0000,
  658.    0x0000,0x7800,0x0000,
  659.    0x0000,0x0000,0x0000,
  660.    0x0000,0x0000,0x0000,
  661.    0x0000,0x0000,0x0000,
  662.    0x0000,0x0000,0x0000
  663. };
  664. USHORT RobotIData[] = {
  665. /*   ----   ----   --   These nibbles matter to image. */
  666.    0x0000,0x0000,0x0000,
  667.    0x0000,0x0000,0x0000,
  668.    0x0000,0x0000,0x0000,
  669.    0x0000,0x0000,0x0000,
  670.    0x0007,0x9E00,0x0000,
  671.    0x0004,0x9200,0x0000,
  672.    0x0007,0x9E00,0x0000,
  673.    0x0000,0x0000,0x0000,
  674.    0x0000,0x0000,0x0000,
  675.    0x0000,0x0000,0x0000,
  676.    0x0000,0x0000,0x0000,
  677.    0x0000,0x0000,0x0000,
  678.    0x0000,0x0000,0x0000,
  679.    0x0001,0xF800,0x0000,
  680.    0x0001,0x0800,0x0000,
  681.    0x0001,0xF800,0x0000,
  682.    0x0000,0x0000,0x0000,
  683.    0x0000,0x0000,0x0000,
  684.    0x0000,0x0000,0x0000,
  685.    0x0000,0x0000,0x0000
  686. };
  687. USHORT FaceIData[] = {
  688. /*   ----   ----   --   These nibbles matter to image. */
  689.    0x0000,0x0000,0x0000,
  690.    0x0000,0x0000,0x0000,
  691.    0x0000,0x0000,0x0000,
  692.    0x0000,0x0000,0x0000,
  693.    0x0000,0x0000,0x0000,
  694.    0x0000,0x0000,0x0000,
  695.    0x0000,0x0000,0x0000,
  696.    0x0000,0x0000,0x0000,
  697.    0x0000,0x0000,0x0000,
  698.    0x0000,0x0000,0x0000
  699. };
  700. USHORT StopIData[] = {
  701. /*   ----   ----   --   These nibbles matter to image. */
  702.    0x0000,0x0000,0x0000,
  703.    0x0000,0x0000,0x0000,
  704.    0x0000,0x0000,0x0000,
  705.    0x0000,0x0000,0x0000,
  706.    0x0000,0x0000,0x0000,
  707.    0x0000,0x0000,0x0000,
  708.    0x0000,0x0000,0x0000,
  709.    0x0000,0x0000,0x0000,
  710.    0x0000,0x0000,0x0000,
  711.    0x0000,0x0000,0x0000
  712. };
  713. USHORT *FemaleIData_chip = 0;
  714. USHORT *MaleIData_chip = 0;
  715. USHORT *HumanIData_chip = 0;
  716. USHORT *RobotIData_chip = 0;
  717. USHORT *FaceIData_chip = 0;
  718. USHORT *StopIData_chip = 0;
  719.  
  720. /** start of code ***************************/
  721. main()
  722. {
  723.    ULONG Signals;        /* Wait() tells me which to look at */
  724.    ULONG MIClass;        /* Save quickly, ReplyMsg() asap */
  725.    USHORT MICode;        /* These hold my needed information */
  726.    APTR MIAddress;
  727.  
  728.    /* let MyCleanup know these signals not allocated yet */
  729.    talk_port.mp_SigBit = -1;
  730.    read_port.mp_SigBit = -1;
  731.  
  732.    /* Open those libraries that the program uses directly */
  733.    if ((IntuitionBase = (struct IntuitionBase *)
  734.     OpenLibrary("intuition.library", LIBRARY_VERSION)) == 0) {
  735. #ifdef DEBUG
  736.       printf("Can't open the intuition library\n");
  737. #endif
  738.       MyCleanup();
  739.       exit(FALSE);
  740.    }
  741.  
  742.    if ((GfxBase = (struct GfxBase *)
  743.     OpenLibrary("graphics.library", LIBRARY_VERSION)) == 0) {
  744. #ifdef DEBUG
  745.       printf("Can't open the graphics library\n");
  746. #endif
  747.       MyCleanup();
  748.       exit(FALSE);
  749.    }
  750.  
  751.    if ((TranslatorBase = (struct Library *)
  752.     OpenLibrary("translator.library", LIBRARY_VERSION)) == 0) {
  753. #ifdef DEBUG
  754.       printf("Can't open the translator library\n");
  755. #endif
  756.       MyCleanup();
  757.       exit(FALSE);
  758.    }
  759.  
  760.    /* Open the device */
  761.    if ((NarratorOpenError = OpenDevice("narrator.device", 0,
  762.     &voice_io, 0)) != 0) {
  763. #ifdef DEBUG
  764.       printf("Can't open the narrator device\n");
  765. #endif
  766.       MyCleanup();
  767.       exit(FALSE);
  768.    }
  769.    /* This is where the proportional gadgets are set up, using
  770.     * the templates that were declared staticly.
  771.     */
  772.    for(PropCount = 0; PropCount < NUMPROPS; PropCount++) {
  773.       PTexts[PropCount] = TPropText;
  774.       Props[PropCount] = TPropGadget;
  775.       PInfos[PropCount] = TPropInfo;
  776.       Props[PropCount].GadgetText = (struct IntuiText *)
  777.        &PTexts[PropCount];
  778.       Props[PropCount].GadgetRender = (APTR)
  779.        &PImages[PropCount];
  780.       Props[PropCount].SpecialInfo = (APTR)&PInfos[PropCount];
  781.       switch (PropCount) {
  782.       case 0:
  783.          PTexts[PropCount].IText = "Sample Freq:";
  784.          if (DEFFREQ == MAXFREQ)
  785.             PInfos[PropCount].HorizPot = 65535;
  786.          else
  787.             PInfos[PropCount].HorizPot = ((DEFFREQ - MINFREQ)
  788.              << 16) / (MAXFREQ - MINFREQ);
  789.          break;
  790.       case 1:
  791.          PTexts[PropCount].IText = "Rate:";
  792.          Props[PropCount].TopEdge += 22;
  793.          Props[PropCount].NextGadget = &Props[PropCount-1];
  794.          if (DEFRATE == MAXRATE)
  795.             PInfos[PropCount].HorizPot = 65535;
  796.          else
  797.             PInfos[PropCount].HorizPot = ((DEFRATE - MINRATE)
  798.              << 16) / (MAXRATE - MINRATE);
  799.          break;
  800.       case 2:
  801.          PTexts[PropCount].IText = "Pitch:";
  802.          Props[PropCount].LeftEdge += 183;
  803.          Props[PropCount].NextGadget = &Props[PropCount-1];
  804.          if (DEFPITCH == MAXPITCH)
  805.             PInfos[PropCount].HorizPot = 65535;
  806.          else
  807.             PInfos[PropCount].HorizPot = ((DEFPITCH-MINPITCH)
  808.              << 16) / (MAXPITCH - MINPITCH);
  809.          break;
  810.       case 3:
  811.          PTexts[PropCount].IText = "Volume:";
  812.          Props[PropCount].TopEdge += 22;
  813.          Props[PropCount].LeftEdge += 183;
  814.          Props[PropCount].NextGadget = &Props[PropCount-1];
  815.          if (DEFVOL == MAXVOL)
  816.             PInfos[PropCount].HorizPot = 65535;
  817.          else
  818.             PInfos[PropCount].HorizPot = ((DEFVOL - MINVOL)
  819.              << 16) / (MAXVOL - MINVOL);
  820.          break;
  821.       }
  822.    }
  823.  
  824.    /* Now allocate memory accessable by the chips for images */
  825.    if (InitImages() != TRUE) {
  826. #ifdef DEBUG
  827.       printf("Couldn't Allocate Images in chip memory.\n");
  828. #endif
  829.       MyCleanup();
  830.       exit(FALSE);
  831.    }
  832.  
  833.    /* Set up the write port, allocate the signal, */
  834.    /* and the message */
  835.    talk_port.mp_Node.ln_Type = NT_MSGPORT;
  836.    talk_port.mp_Flags = 0;
  837.    if ((talk_port.mp_SigBit = AllocSignal(-1)) == -1) {
  838. #ifdef DEBUG
  839.       printf("Couldn't Allocate talk Signal bit\n");
  840. #endif
  841.       MyCleanup();
  842.       exit(FALSE);
  843.    }
  844.    talk_port.mp_SigTask = (struct Task *) FindTask((char *)
  845.     NULL);
  846.    NewList(&talk_port.mp_MsgList);
  847.  
  848.    /* Set up the read port, allocate the signal, */
  849.    /*  and the message */
  850.    read_port.mp_Node.ln_Type = NT_MSGPORT;
  851.    read_port.mp_Flags = 0;
  852.    if ((read_port.mp_SigBit = AllocSignal(-1)) == -1) {
  853. #ifdef DEBUG
  854.       printf("Couldn't Allocate read Signal bit\n");
  855. #endif
  856.       MyCleanup();
  857.       exit(FALSE);
  858.    }
  859.    read_port.mp_SigTask = (struct Task *)
  860.     FindTask((char *) NULL);
  861.    NewList(&read_port.mp_MsgList);
  862.  
  863.    /* Set up the write channel information */
  864.    voice_io.ch_masks = (audio_chan);
  865.    voice_io.nm_masks = sizeof(audio_chan);
  866.    voice_io.mouths = 0;
  867.    voice_io.message.io_Message.mn_ReplyPort = &talk_port;
  868.    voice_io.message.io_Command = CMD_WRITE;
  869.    voice_io.message.io_Offset = 0;
  870.    voice_io.message.io_Data = (APTR)PhonBuffer;
  871.    voice_io.message.io_Message.mn_Length = sizeof(voice_io);
  872.  
  873.   /* Set up the read channel information */
  874.    mouth_io.voice = voice_io;
  875.    mouth_io.width = 0;
  876.    mouth_io.height = 0;
  877.    mouth_io.voice.message.io_Message.mn_ReplyPort = &read_port;
  878.    mouth_io.voice.message.io_Command = CMD_READ;
  879.    mouth_io.voice.message.io_Error = 0;
  880.    if (FaceWindow == NULL) {
  881.       if ((ControlWindow = (struct Window *)OpenWindow
  882.        (&NewControlWindow)) == NULL) {
  883. #ifdef DEBUG
  884.          printf("Couldn't open the control window.\n");
  885. #endif
  886.          MyCleanup();
  887.          exit(FALSE);
  888.       }
  889.    }
  890.  
  891.    /* fill background of window */
  892.    SetAPen(ControlWindow->RPort, BLKP);
  893.    RectFill(ControlWindow->RPort,0,0,
  894.     ControlWindow->GZZWidth, ControlWindow->GZZHeight);
  895.    RefreshGadgets(&Props[NUMPROPS-1],ControlWindow,NULL);
  896.  
  897.    SetMenuStrip(ControlWindow, &MyMenu);
  898.  
  899. /* !!! Ah, But what if FaceWindow's not been opened? */
  900.    for (;;) {  /* ever wait for a signal and process it */
  901.       /* wait lets the rest of the system run, */
  902.       /* this program sleeps */
  903.       Signals = Wait((1 << ControlWindow->UserPort->mp_SigBit)
  904. | (1 << FaceWindow->UserPort->mp_SigBit)
  905. | (1 << voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)
  906. | (1 <<
  907.    mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit));
  908.       /* now check to see to what we owe the intrusion */
  909.  
  910.       if (Signals & (1<< ControlWindow->UserPort->mp_SigBit)) {
  911.          /* Process the Intuition message */
  912.          while (MyIntuiMessage=(struct IntuiMessage *)
  913.                       GetMsg(ControlWindow->UserPort)) {
  914.             /* Get all the needed info and give message back */
  915.             MIClass = MyIntuiMessage->Class;
  916.             MICode = MyIntuiMessage->Code;
  917.             MIAddress = MyIntuiMessage->IAddress;
  918.             ReplyMsg(MyIntuiMessage);
  919.             /* Now, what was it you wanted? */
  920.             switch (MIClass) {
  921.                case MENUPICK:
  922.                   menumessage(MICode, ControlWindow);
  923.                   break;
  924.                case GADGETUP:         /* reply, then process */
  925.                   gadgetmessage(MIAddress, ControlWindow);
  926.                   break;
  927.                case CLOSEWINDOW:       /* bye! */
  928.                   while (MyIntuiMessage = (struct
  929.                    IntuiMessage *) GetMsg(
  930.                    ControlWindow->UserPort))
  931.                     ReplyMsg(MyIntuiMessage);
  932.                   MyCleanup();
  933.                   exit(TRUE);
  934.                   break;
  935.                default:
  936. #ifdef DEBUG
  937.                   printf("Unhandled Message Received.\n");
  938. #endif
  939.                   break;
  940.             }  /* switch */
  941.          } /* while */
  942.       } /* if */
  943.  
  944.  
  945.       /* Woken by intuition for FaceWindow*/
  946.       if (Signals & (1<< FaceWindow->UserPort->mp_SigBit)) {
  947.          /* Process the Intuition message */
  948.          while (MyIntuiMessage=(struct IntuiMessage *)
  949.           GetMsg(FaceWindow->UserPort)) {
  950.             switch (MyIntuiMessage->Class) {
  951.                case SIZEVERIFY:
  952.                   ReplyMsg(MyIntuiMessage);
  953.                   break;
  954.                case MENUPICK:
  955.                   menumessage(MyIntuiMessage->Code,FaceWindow);
  956.                   ReplyMsg(MyIntuiMessage);
  957.                   break;
  958.                case NEWSIZE:  /* Don't reply until processed */
  959.                   DrawFace();
  960.                   ReplyMsg(MyIntuiMessage);
  961.                   break;
  962.                default:
  963. #ifdef DEBUG
  964.                   printf("Unhandled Message Received.\n");
  965. #endif
  966.                   ReplyMsg(MyIntuiMessage);
  967.                   break;
  968.             }  /* switch */
  969.          } /* while */
  970.       } /* if */
  971.  
  972.       /* A voice SendIO (Write) has completed */
  973.       if (Signals & (1 <<
  974.        voice_io.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  975.          /* Was it Sucessful? filter out the abort error */
  976.          if (voice_io.message.io_Error == -2)
  977.             voice_io.message.io_Error = 0;
  978.          if (voice_io.message.io_Error != 0) {
  979. #ifdef DEBUG
  980.             printf("Narrator won't. (%ld)\n",
  981.              voice_io.message.io_Error);
  982. #endif
  983.             /* flash this screen */
  984.             DisplayBeep(ControlWindow->WScreen);
  985.             /* let user see where phoneme string was bad. */
  986.             i = RemoveGadget(ControlWindow, &PhonStrGadget);
  987.             /* move the cursor to the error char */
  988.             PhonInfo.BufferPos = voice_io.message.io_Actual -1;
  989.             /* assure cursor (error point) is shown in gad. */
  990.             /* within 29 (number of chars shown) of front */
  991.             if (voice_io.message.io_Actual < 29)
  992.                PhonInfo.DispPos = 0;
  993.             /* within 29 of end */
  994.             else if ((voice_io.message.io_Length -
  995.                       voice_io.message.io_Actual) < 29)
  996.                PhonInfo.DispPos = voice_io.message.io_Length
  997.                                   - 29;
  998.             else
  999.                PhonInfo.DispPos = voice_io.message.io_Actual
  1000.                                   - 15;
  1001.             AddGadget(ControlWindow, &PhonStrGadget, i);
  1002.             RefreshGadgets(&PhonStrGadget, ControlWindow,
  1003.              NULL);
  1004.             voice_io.message.io_Error = 0;
  1005.          }
  1006. /*       SpeakGadget.Flags ^= GADGDISABLED;
  1007.          FaceGadget.Flags ^= GADGDISABLED;
  1008. */
  1009.          OnGadget(&SpeakGadget, ControlWindow, NULL);
  1010.          OnGadget(&FaceGadget,  ControlWindow, NULL);
  1011.       }
  1012.  
  1013.       /* A mouth DoIO (Read) has completed */
  1014.       if (Signals & (1 <<
  1015.   mouth_io.voice.message.io_Message.mn_ReplyPort->mp_SigBit)) {
  1016.          WaitBOVP(&FaceWindow->WScreen->ViewPort);
  1017.          SetAPen(FaceWindow->RPort, WHTP);
  1018.          RectFill(FaceWindow->RPort, 0, EyesBottom,
  1019.           FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1020.          if (MouthWMult == 0)
  1021.             LipWidth = mouth_io.width >> 1;
  1022.          else
  1023.             LipWidth = mouth_io.width * MouthWMult;
  1024.          if (MouthHMult == 0)
  1025.             LipHeight = mouth_io.height >> 1;
  1026.          else
  1027.             LipHeight = mouth_io.height * (MouthHMult);
  1028.          SetAPen(FaceWindow->RPort, REDP);
  1029.          Move(FaceWindow->RPort,
  1030.           XMouthCenter - LipWidth, YMouthCenter);
  1031.          Draw(FaceWindow->RPort,
  1032.           XMouthCenter, YMouthCenter - LipHeight);
  1033.          Draw(FaceWindow->RPort,
  1034.           XMouthCenter + LipWidth, YMouthCenter);
  1035.          Draw(FaceWindow->RPort,
  1036.           XMouthCenter, YMouthCenter + LipHeight);
  1037.          Draw(FaceWindow->RPort,
  1038.           XMouthCenter - LipWidth, YMouthCenter);
  1039.          /* the narrator will give an error when the */
  1040.          /* write has completed and I've tried to read */
  1041.          /* so I stop trying when that happens */
  1042.          if (mouth_io.voice.message.io_Error == 0)
  1043.             SendIO(&mouth_io);
  1044.       }
  1045.    }  /* for */
  1046. }  /* main */
  1047.  
  1048. /* a MENUPICK has been received, this
  1049.  * routine takes the appropriate action
  1050.  */
  1051. menumessage(code, w)
  1052. USHORT code;
  1053. struct Window *w;
  1054. {
  1055.    switch (MENUNUM(code)) {
  1056.       case 0:
  1057.          switch (ITEMNUM(code)) {
  1058.             case 0:
  1059.                AutoRequest(w, &ReqText3, NULL,
  1060.                            &OKIText, 0, 0, 280, 47);
  1061.                break;
  1062.          }
  1063.       break;
  1064.    }
  1065. }
  1066.  
  1067. /* a GADGETUP has been received, this
  1068.  * routine takes the appropriate action
  1069.  */
  1070. gadgetmessage(address, w)
  1071. APTR address;
  1072. struct Window *w;
  1073. {
  1074.    USHORT i;
  1075.    long PropRange;
  1076.    if (address == (APTR)&ModeGadget) {
  1077.       if (ModeGadget.Flags & SELECTED)
  1078.          voice_io.mode = ROBOTICF0;
  1079.       else
  1080.          voice_io.mode = NATURALF0;
  1081.    }
  1082.    else if (address == (APTR)&FaceGadget) {
  1083.       /* tell the write that reads will be forthcomming */
  1084.       if (FaceGadget.Flags & SELECTED) {
  1085.          voice_io.mouths = 1;
  1086.          if ((FaceWindow = (struct Window *)
  1087.           OpenWindow(&NewFaceWindow)) == NULL) {
  1088. #ifdef DEBUG
  1089.             printf("Couldn't open the face window.\n");
  1090. #endif
  1091.             MyCleanup();
  1092.             exit(FALSE);
  1093.          }
  1094.          SetMenuStrip(FaceWindow, &MyMenu);
  1095.          DrawFace();
  1096.       }
  1097.       else { /* FaceGadget de-SELECTed */
  1098.          voice_io.mouths = 0;
  1099.          NewFaceWindow.LeftEdge = FaceWindow->LeftEdge;
  1100.          NewFaceWindow.TopEdge = FaceWindow->TopEdge;
  1101.          NewFaceWindow.Width = FaceWindow->Width;
  1102.          NewFaceWindow.Height = FaceWindow->Height;
  1103.          CloseWindow(FaceWindow);
  1104.          FaceWindow = NULL;
  1105.       }
  1106.    }
  1107.    else if (address == (APTR)&StopGadget) {
  1108.       AbortIO(&voice_io);
  1109.       voice_io.message.io_Error = 0;
  1110.       mouth_io.voice.message.io_Error = 0;
  1111.    }
  1112.    /* Since this program changes a flag that intuition expects
  1113.     * only the user to change (SELECTED bit), this program has
  1114.     * to remove, then change, then add this gadget. Then by
  1115.     * passing the address of this gadget to RefreshGadgets(),
  1116.     * only the gadgets from here to the start of the list will
  1117.     * be refreshed, which minimizes the visible flash that
  1118.     * RefreshGadgets() can introduce.
  1119.     * If one of the two gadgets (female/male) is hit, toggle
  1120.     * the selection of the other gadget (since the gadget hit
  1121.     * was toggled by intuition when it was hit).
  1122.     */
  1123.    else if (address == (APTR)&FemaleGadget) {
  1124.       if (FemaleGadget.Flags & SELECTED)
  1125.       voice_io.sex = FEMALE;
  1126.       else
  1127.       voice_io.sex = MALE;
  1128.       i = RemoveGadget(ControlWindow, &MaleGadget);
  1129.       MaleGadget.Flags ^= SELECTED;
  1130.       AddGadget(ControlWindow, &MaleGadget, i);
  1131.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1132.    }
  1133.    else if (address == (APTR)&MaleGadget) {
  1134.       if (MaleGadget.Flags & SELECTED)
  1135.       voice_io.sex = MALE;
  1136.       else
  1137.       voice_io.sex = FEMALE;
  1138.       i = RemoveGadget(ControlWindow, &FemaleGadget);
  1139.       FemaleGadget.Flags ^= SELECTED;
  1140.       AddGadget(ControlWindow, &FemaleGadget, i);
  1141.       RefreshGadgets(&MaleGadget, ControlWindow, NULL);
  1142.    }
  1143.    /* Since the program changes the contents of the string
  1144.     * gadgets' buffer and it's size, which is something else
  1145.     * intuition doesn't expect a program (as opposed to the
  1146.     * user) to do. The program must remove, then change, then
  1147.     * add this gadget, and then by passing the address of this
  1148.     * gadget to RefreshGadgets(), only the gadgets from here
  1149.     * to the start of the list will be refreshed, which
  1150.     * minimizes the visible flash that RefreshGadgets() can
  1151.     * introduce.
  1152.     */
  1153.    else if (address == (APTR)&TranslateGadget) {
  1154.       i = RemoveGadget(ControlWindow, &PhonStrGadget);
  1155.       if ((TranslatorError = Translate((APTR)EnglBuffer,
  1156.        EnglInfo.NumChars, (APTR)PhonBuffer, PhonInfo.MaxChars))
  1157.        != 0) {
  1158. #ifdef DEBUG
  1159.          printf("Translator won't. (%lx)\n",TranslatorError);
  1160. #endif
  1161.          /* flash this screen */
  1162.          DisplayBeep(ControlWindow->WScreen);
  1163.       }
  1164.       /* Hey! NumChars includes the terminating NULL. */
  1165.       /* This must be done. */
  1166.       PhonInfo.NumChars = voice_io.message.io_Length + 1;
  1167.       if (PhonInfo.DispPos > voice_io.message.io_Length)
  1168.           PhonInfo.DispPos = voice_io.message.io_Length;
  1169.       AddGadget(ControlWindow, &PhonStrGadget, i);
  1170.       RefreshGadgets(&PhonStrGadget, ControlWindow, NULL);
  1171.    }
  1172.    else if (address == (APTR)&SpeakGadget) {
  1173. /*    SpeakGadget.Flags ^= GADGDISABLED;
  1174.       FaceGadget.Flags ^= GADGDISABLED;
  1175. */
  1176.       OffGadget(&SpeakGadget, ControlWindow, NULL);
  1177.       OffGadget(&FaceGadget,  ControlWindow, NULL);
  1178.  
  1179.       voice_io.message.io_Length = strlen(PhonBuffer);
  1180.       SendIO(&voice_io);
  1181.       if (voice_io.mouths == 1) {
  1182.          mouth_io.voice.message.io_Error = 0;
  1183.          SendIO(&mouth_io);
  1184.       }
  1185.    }
  1186.    else if (address == (APTR)&EnglStrGadget);  /* do nothing */
  1187.    else if (address == (APTR)&PhonStrGadget);  /* do nothing */
  1188.    else if (address == (APTR)&Props[0]) {
  1189.       PropRange = RNGFREQ;
  1190.       voice_io.sampfreq = (( (PInfos[0].HorizPot >> 1)
  1191.        * PropRange) >> 15) + MINFREQ;
  1192. #ifdef DEBUG
  1193.       printf("Freq. = %ld\n", voice_io.sampfreq);
  1194. #endif
  1195.    }
  1196.    else if (address == (APTR)&Props[1]) {
  1197.       PropRange = RNGRATE;
  1198.       voice_io.rate = (((PInfos[1].HorizPot >> 1)
  1199.        * PropRange) >> 15) + MINRATE;
  1200. #ifdef DEBUG
  1201.       printf("Rate  = %ld\n", voice_io.rate);
  1202. #endif
  1203.    }
  1204.    else if (address == (APTR)&Props[2]) {
  1205.       PropRange = RNGPITCH;
  1206.       voice_io.pitch = (((PInfos[2].HorizPot >> 1)
  1207.        * PropRange) >> 15) + MINPITCH;
  1208. #ifdef DEBUG
  1209.       printf("Pitch = %ld\n", voice_io.pitch);
  1210. #endif
  1211.    }
  1212.    else if (address == (APTR)&Props[3]) {
  1213.       PropRange = RNGVOL;
  1214.       voice_io.volume = (((PInfos[3].HorizPot >> 1)
  1215.        * PropRange) >> 15) + MINVOL;
  1216. #ifdef DEBUG
  1217.       printf("Vol.  = %ld\n", voice_io.volume);
  1218. #endif
  1219.    }
  1220. #ifdef DEBUG
  1221.    else printf("Unhandled gadget up received!\n");
  1222. #endif
  1223. }
  1224.  
  1225. /* This calculates variables used to draw the mouth
  1226.  * and eyes, as well as redrawing the face.
  1227.  * Proportionality makes it very wierd, but it's
  1228.  * wierder if you don't use a GimmeZeroZero window
  1229.  * and GZZWidth/GZZHeight.
  1230.  */
  1231. DrawFace() {
  1232.    XMouthCenter =  FaceWindow->GZZWidth >> 1;
  1233.    /* set left edge of left eye */
  1234.    EyesLeft = FaceWindow->GZZWidth >> 2;
  1235.    /* multiplier for mouth width */
  1236.    MouthWMult = FaceWindow->GZZWidth >> 6;
  1237.  
  1238.    EyesTop = (FaceWindow->GZZHeight >> 2)
  1239.     - (FaceWindow->GZZHeight >> 4);
  1240.    EyesBottom = EyesTop + (FaceWindow->GZZHeight >> 3) + 1;
  1241.    yaw = FaceWindow->GZZHeight - EyesBottom;
  1242.    YMouthCenter = ((yaw >> 1) + EyesBottom);
  1243.    MouthHMult = yaw >> 5;
  1244.  
  1245.    /* Set pen to White */
  1246.    SetAPen(FaceWindow->RPort, WHTP);
  1247.    RectFill(FaceWindow->RPort, 0, 0,
  1248.     FaceWindow->GZZWidth, FaceWindow->GZZHeight);
  1249.  
  1250.    /* Set pen to Blue */
  1251.    SetAPen(FaceWindow->RPort, BLUP);
  1252.    RectFill(FaceWindow->RPort,
  1253.     EyesLeft, EyesTop,
  1254.     EyesLeft + (FaceWindow->GZZWidth >> 3),
  1255.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1256.    RectFill(FaceWindow->RPort,
  1257.     (FaceWindow->GZZWidth >> 1)
  1258.     + (FaceWindow->GZZWidth >> 3),
  1259.     EyesTop,
  1260.     (FaceWindow->GZZWidth >> 1)
  1261.      + (FaceWindow->GZZWidth >> 3) /* two >> 3, not one >> 2 */
  1262.      + (FaceWindow->GZZWidth >> 3),/* so eyes are same width */
  1263.     EyesTop + (FaceWindow->GZZHeight >> 3));
  1264.  
  1265.     SetAPen(FaceWindow->RPort, REDP);  /* Set pen to Red */
  1266.     Move(FaceWindow->RPort,
  1267.      XMouthCenter - (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1268.     Draw(FaceWindow->RPort,
  1269.      XMouthCenter + (FaceWindow->GZZWidth >> 3), YMouthCenter);
  1270.  
  1271. }
  1272.  
  1273. /* Deallocate any memory, and close all of the
  1274.  * windows/screens/devices/libraries in reverse order to
  1275.  * make things work smoothly. And be sure to check
  1276.  * that the open/allocation was successful before
  1277.  * closing/deallocating.
  1278.  */
  1279. MyCleanup()
  1280. {
  1281.    if (read_port.mp_SigBit != -1)
  1282.       FreeSignal(read_port.mp_SigBit);
  1283.    if (talk_port.mp_SigBit != -1)
  1284.       FreeSignal(talk_port.mp_SigBit);
  1285.    if (FaceWindow != NULL)
  1286.       CloseWindow(FaceWindow);
  1287.    if (ControlWindow != NULL)
  1288.       CloseWindow(ControlWindow);
  1289.    /* freeimages makes sure image allocation was successful */
  1290.    freeimages();
  1291.    if (NarratorOpenError == 0)
  1292.       CloseDevice(&voice_io);
  1293.    if (TranslatorBase != 0)
  1294.       CloseLibrary(TranslatorBase);
  1295.    if (GfxBase != 0)
  1296.       CloseLibrary(GfxBase);
  1297.    if (IntuitionBase != 0)
  1298.       CloseLibrary(IntuitionBase);
  1299.    return(0);
  1300. }
  1301.  
  1302. /* Allocate chip memory for gadget images, and set the
  1303.  * pointers in the corresponding image structures to point
  1304.  * to these images. This must be done because the program
  1305.  * could be loaded into expansion memory (off the side of
  1306.  * the box), which the custom chips cannot access.
  1307.  * And images must be in chip ram (that's memory that the
  1308.  * custom chips can access, the internal 512K).
  1309.  */
  1310. InitImages()
  1311. {
  1312.    /* the images were staticly initialized above main */
  1313.    extern USHORT *FemaleIData_chip;
  1314.    extern USHORT *MaleIData_chip;
  1315.    extern USHORT *HumanIData_chip;
  1316.    extern USHORT *RobotIData_chip;
  1317.    extern USHORT *FaceIData_chip;
  1318.    extern USHORT *StopIData_chip;
  1319.    int i;
  1320.  
  1321.    /* Allocate them all, stop and return false on failure */
  1322.    if ((FemaleIData_chip = (USHORT *)
  1323.     AllocMem(sizeof(FemaleIData),MEMF_CHIP)) == 0)
  1324.       return(FALSE);
  1325.    if ((MaleIData_chip = (USHORT *)
  1326.     AllocMem(sizeof(MaleIData),MEMF_CHIP)) == 0)
  1327.       return(FALSE);
  1328.    if ((HumanIData_chip = (USHORT *)
  1329.     AllocMem(sizeof(HumanIData),MEMF_CHIP)) == 0)
  1330.       return(FALSE);
  1331.    if ((RobotIData_chip = (USHORT *)
  1332.     AllocMem(sizeof(RobotIData),MEMF_CHIP)) == 0)
  1333.       return(FALSE);
  1334.    if ((FaceIData_chip = (USHORT *)
  1335.     AllocMem(sizeof(FaceIData),MEMF_CHIP)) == 0)
  1336.       return(FALSE);
  1337.    if ((StopIData_chip = (USHORT *)
  1338.     AllocMem(sizeof(StopIData),MEMF_CHIP)) == 0)
  1339.       return(FALSE);
  1340.  
  1341.    for (i=0; i<20; i++)
  1342.       FemaleIData_chip[i] = FemaleIData[i];
  1343.    for (i=0; i<20; i++)
  1344.       MaleIData_chip[i] = MaleIData[i];
  1345.    for (i=0; i<60; i++)
  1346.       HumanIData_chip[i] = HumanIData[i];
  1347.    for (i=0; i<60; i++)
  1348.       RobotIData_chip[i] = RobotIData[i];
  1349.    for (i=0; i<30; i++)
  1350.       FaceIData_chip[i] = FaceIData[i];
  1351.    for (i=0; i<30; i++)
  1352.       StopIData_chip[i] = StopIData[i];
  1353.  
  1354.    FemaleImage.ImageData = FemaleIData_chip;
  1355.    MaleImage.ImageData = MaleIData_chip;
  1356.    HumanImage.ImageData = HumanIData_chip;
  1357.    RobotImage.ImageData = RobotIData_chip;
  1358.    FaceImage.ImageData = FaceIData_chip;
  1359.    StopImage.ImageData = StopIData_chip;
  1360.  
  1361.    return(TRUE);
  1362. }
  1363.  
  1364. /* Deallocate the memory that was used for images,
  1365.  * See initimages for more details.
  1366.  */
  1367. freeimages()
  1368. {
  1369.    /* the images were staticly initialized above main */
  1370.    extern USHORT *FemaleIData_chip;
  1371.    extern USHORT *MaleIData_chip;
  1372.    extern USHORT *HumanIData_chip;
  1373.    extern USHORT *RobotIData_chip;
  1374.    extern USHORT *FaceIData_chip;
  1375.    extern USHORT *StopIData_chip;
  1376.  
  1377.    /* Deallocate only if the pointer is really there. */
  1378.    if (RobotIData_chip != 0)
  1379.       FreeMem(RobotIData_chip, sizeof(RobotIData));
  1380.    if (HumanIData_chip != 0)
  1381.       FreeMem(HumanIData_chip, sizeof(HumanIData));
  1382.    if (MaleIData_chip != 0)
  1383.       FreeMem(MaleIData_chip, sizeof(MaleIData));
  1384.    if (FemaleIData_chip != 0)
  1385.       FreeMem(FemaleIData_chip, sizeof(FemaleIData));
  1386.    if (FaceIData_chip != 0)
  1387.       FreeMem(FaceIData_chip, sizeof(FaceIData));
  1388.    if (StopIData_chip != 0)
  1389.       FreeMem(StopIData_chip, sizeof(StopIData));
  1390. }
  1391.